package com.ctshk.rpc.system.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.enums.IsDeletedCode;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.rpc.system.dto.*;
import com.ctshk.rpc.system.entity.MainDataField;
import com.ctshk.rpc.system.entity.MainDataFieldData;
import com.ctshk.rpc.system.entity.MainDataRowData;
import com.ctshk.rpc.system.entity.MainDataTable;
import com.ctshk.rpc.system.mapper.MainDataFieldDataMapper;
import com.ctshk.rpc.system.mapper.MainDataFieldMapper;
import com.ctshk.rpc.system.mapper.MainDataRowDataMapper;
import com.ctshk.rpc.system.mapper.MainDataTableMapper;
import com.ctshk.rpc.system.req.MainDataQueryReq;
import com.ctshk.rpc.system.req.MainDataRowFieldDataReq;
import com.ctshk.rpc.system.req.MainDataTableQueryReq;
import com.ctshk.rpc.system.req.MainDataTableReq;
import com.ctshk.rpc.system.service.IMainDataTableService;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 基础数据模板表 服务实现类
 * </p>
 *
 * @author 谢诗宏
 * @since 2020-12-29
 */
@DubboService
public class MainDataTableServiceImpl extends ServiceImpl<MainDataTableMapper, MainDataTable> implements IMainDataTableService {

    /**
     * 数据表服务
     */
    @Autowired
    private MainDataTableMapper mainDataTableMapper;

    /**
     * 主数据表字段
     */
    @Autowired
    private MainDataFieldMapper mainDataFieldMapper;

    /**
     * 行数据
     */
    @Autowired
    private MainDataRowDataMapper mainDataRowDataMapper;

    /**
     * 表字段数据
     */
    @Autowired
    private MainDataFieldDataMapper mainDataFieldDataMapper;

    @Override
    public void add(MainDataTableReq mainDataTableReq, Long usrId) {
        MainDataTable mainDataTable = new MainDataTable();
        BeanUtils.copyProperties(mainDataTableReq, mainDataTable);
        mainDataTable.setCreateId(usrId);
        mainDataTable.setIsDeleted(0);
        mainDataTable.setStatus(0);
        mainDataTableMapper.insert(mainDataTable);
    }

    @Override
    public PageResponse<MainDataTableDTO> queryList(MainDataTableQueryReq mainDataTableQueryReq, Long userId) {

        IPage<MainDataTable> page = new Page<MainDataTable>(mainDataTableQueryReq.getPageNo(), mainDataTableQueryReq.getPageSize());
        QueryWrapper<MainDataTable> queryWrapper = new QueryWrapper<MainDataTable>();
        queryWrapper.lambda().eq(MainDataTable::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(mainDataTableQueryReq.getModule() != null, MainDataTable::getModule, mainDataTableQueryReq.getModule())
                .like(StringUtils.isNotBlank(mainDataTableQueryReq.getTableName()), MainDataTable::getTableName, mainDataTableQueryReq.getTableName())
                .orderByDesc(MainDataTable::getGmtCreate);

        IPage<MainDataTable> iPage = mainDataTableMapper.selectPage(page, queryWrapper);
        List<MainDataTable> mainDataTableList = iPage.getRecords();
        List<MainDataTableDTO> mainDataTableDTOList = EntityUtil.copyList(mainDataTableList, MainDataTableDTO.class);
        if (CollectionUtils.isNotEmpty(mainDataTableDTOList)) {
            //行数据里表字段对应的值
            List<Long> tableIdList = mainDataTableList.stream().map(MainDataTable::getId).collect(Collectors.toList());
            List<MainDataField> mainDataFieldList = mainDataFieldMapper.selectList(new QueryWrapper<MainDataField>().lambda().in(MainDataField::getTableId, tableIdList).eq(MainDataField::getIsDeleted, 0));
            if (CollectionUtils.isNotEmpty(mainDataFieldList)) {
                List<MainDataFieldDTO> fieldList = EntityUtil.copyList(mainDataFieldList, MainDataFieldDTO.class);

                //内存计算、转行为map进行对比筛选
                HashMap<Long, List<MainDataFieldDTO>> hashMap = new HashMap<>();
                for (MainDataFieldDTO mainDataFieldDTO : fieldList) {
                    Long tableId = mainDataFieldDTO.getTableId();
                    List<MainDataFieldDTO> dataFieldList = hashMap.get(tableId);
                    if (CollectionUtils.isEmpty(dataFieldList)) {
                        dataFieldList = new ArrayList<>();
                    }
                    dataFieldList.add(mainDataFieldDTO);
                    hashMap.put(tableId, dataFieldList);
                }

                for (MainDataTableDTO mainDataTableDTO : mainDataTableDTOList) {
                    mainDataTableDTO.setFieldList(hashMap.get(mainDataTableDTO.getId()));
                }
            }
        }

        return new PageResponse<>(mainDataTableDTOList, iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());

    }

    @Override
    public PageResponse<MainDataRowDataDTO> queryTable(MainDataQueryReq mainDataQueryReq) {
        Long tableId = mainDataQueryReq.getTableId();
        //主数表名称数据
        IPage<MainDataRowData> page = new Page<>(mainDataQueryReq.getPageNo(), mainDataQueryReq.getPageSize());

        // 行数据
        QueryWrapper<MainDataRowData> queryWrapper = new QueryWrapper<MainDataRowData>();
        queryWrapper.lambda().eq(MainDataRowData::getTableId, tableId).eq(MainDataRowData::getIsDeleted, 0);
        if (mainDataQueryReq.getStatus() != null) {
            queryWrapper.lambda().eq(MainDataRowData::getStatus, mainDataQueryReq.getStatus());
        }
        List<MainDataRowDataDTO> mainDataRowDataDTOList = new ArrayList<>();
        if (StringUtils.isNotBlank(mainDataQueryReq.getTextName())) {
            QueryWrapper<MainDataFieldData> dataQueryWrapper = new QueryWrapper<>();
            dataQueryWrapper.lambda().eq(MainDataFieldData::getTableId, mainDataQueryReq.getTableId()).eq(MainDataFieldData::getIsDeleted, 0).like(MainDataFieldData::getFieldValue, mainDataQueryReq.getTextName());

            //行页码
            IPage<MainDataFieldData> pageRow = new Page<>(mainDataQueryReq.getPageNo(), mainDataQueryReq.getPageSize());
            IPage<MainDataFieldData> fieldDataPage = mainDataFieldDataMapper.selectPage(pageRow, dataQueryWrapper);
            List<MainDataFieldData> fieldList = fieldDataPage.getRecords();

            if (CollectionUtils.isEmpty(fieldList)) {
                return new PageResponse<>(mainDataRowDataDTOList, page.getCurrent() == 1, page.getTotal() <= (page.getCurrent() * page.getSize()), page.getTotal(), page.getCurrent(), page.getSize());
            }
            // 搜索匹配完之后的row数据
            List<Long> rowList = fieldList.stream().map(MainDataFieldData::getRowId).collect(Collectors.toList());
            queryWrapper.lambda().in(MainDataRowData::getId, rowList);
        }

        IPage<MainDataRowData> iPage = mainDataRowDataMapper.selectPage(page, queryWrapper);
        List<MainDataRowData> mainDataRowDataList = iPage.getRecords();


        if (CollectionUtils.isEmpty(mainDataRowDataList)) {
            return new PageResponse<>(mainDataRowDataDTOList, page.getCurrent() == 1, page.getTotal() <= (page.getCurrent() * page.getSize()), page.getTotal(), page.getCurrent(), page.getSize());
        }
        //行数据里表字段对应的值
        List<Long> rowIdList = mainDataRowDataList.stream().map(MainDataRowData::getId).collect(Collectors.toList());
        List<MainDataFieldData> mainDataFieldDataList = mainDataFieldDataMapper.selectList(new QueryWrapper<MainDataFieldData>().lambda().in(MainDataFieldData::getRowId, rowIdList).eq(MainDataFieldData::getIsDeleted, 0));

        List<MainDataFieldDataDTO> dataFieldDataList = EntityUtil.copyList(mainDataFieldDataList, MainDataFieldDataDTO.class);

        HashMap<Long, List<MainDataFieldDataDTO>> hashMap = new HashMap<>(dataFieldDataList.size());

        for (MainDataFieldDataDTO mainDataFieldDataDTO : dataFieldDataList) {
            Long rowId = mainDataFieldDataDTO.getRowId();
            List<MainDataFieldDataDTO> fieldDataList = hashMap.get(rowId);
            if (CollectionUtils.isEmpty(fieldDataList)) {
                fieldDataList = new ArrayList<>();
            }
            fieldDataList.add(mainDataFieldDataDTO);
            hashMap.put(rowId, fieldDataList);
        }

        //核对填充结构
        List<MainDataField> mainDataFields = mainDataFieldMapper.selectList(Wrappers.<MainDataField>lambdaQuery()
                .eq(MainDataField::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(MainDataField::getTableId, mainDataQueryReq.getTableId())
        );
        MainDataRowDataDTO mainDataRowDataDTO = null;
        for (MainDataRowData mainDataRowData : mainDataRowDataList) {
            mainDataRowDataDTO = new MainDataRowDataDTO();
            mainDataRowDataDTO.setStatus(mainDataRowData.getStatus());
            Long rowId = mainDataRowData.getId();
            mainDataRowDataDTO.setRowId(rowId);
            mainDataRowDataDTO.setFieldDataList(hashMap.get(rowId));
            if (hashMap.get(rowId) == null) {
                continue;//如果这一行没有数据就跳过
            }
            if (mainDataRowDataDTO.getFieldDataList() != null) {
                List<MainDataFieldDataDTO> fieldDataList = mainDataRowDataDTO.getFieldDataList();
                List<Long> collect = fieldDataList.stream().map(e -> e.getFieldId()).collect(Collectors.toList());
                List<Long> collect2 = mainDataFields.stream().map(e -> e.getId()).collect(Collectors.toList());
                if (!collect.containsAll(collect2)) {
                    mainDataFields.forEach(field -> {
                        if (!collect.contains(field.getId())) {
                            MainDataFieldDataDTO copy = EntityUtil.copy(fieldDataList.get(0), MainDataFieldDataDTO.class);
                            copy.setId(IdWorker.getId());
                            copy.setFieldId(field.getId());
                            copy.setFieldValue("");
                            fieldDataList.add(copy);
                        }
                    });
                }
            }
            mainDataRowDataDTOList.add(mainDataRowDataDTO);
        }

        PageResponse<MainDataRowDataDTO> pageResponse = new PageResponse<>(mainDataRowDataDTOList, page.getCurrent() == 1, page.getTotal() <= (page.getCurrent() * page.getSize()), page.getTotal(), page.getCurrent(), page.getSize());
        return pageResponse;
    }

    @Override
    public PageResponse<MainDataRowDataListDTO> queryTableList(MainDataQueryReq mainDataQueryReq) {
        PageResponse<MainDataRowDataDTO> response = this.queryTable(mainDataQueryReq);
        if (CollectionUtils.isEmpty(response.getRecords())) {
            return new PageResponse<>(new ArrayList<>(), response.getIsFirst(), response.getIsLast(), response.getTotal(), response.getPageNo(), response.getPageSize());
        }
        List<MainDataRowDataDTO> records = response.getRecords();
        List<MainDataRowDataDTO> list = JSON.parseArray(JSON.toJSONString(records), MainDataRowDataDTO.class);
        List<MainDataRowDataListDTO> mainDataRowDataListDTOS = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            MainDataRowDataListDTO mainDataRowDataListDTO = new MainDataRowDataListDTO();
            MainDataRowDataDTO mainDataRowDataDTO = list.get(i);
            if (CollectionUtils.isNotEmpty(mainDataRowDataDTO.getFieldDataList())) {
                mainDataRowDataListDTO.setCode(mainDataRowDataDTO.getFieldDataList().get(0).getFieldValue());
                mainDataRowDataListDTO.setName(mainDataRowDataDTO.getFieldDataList().get(1).getFieldValue());
                mainDataRowDataListDTO.setStatus(mainDataRowDataDTO.getStatus());
                mainDataRowDataListDTO.setRowId(mainDataRowDataDTO.getRowId());
                mainDataRowDataListDTOS.add(mainDataRowDataListDTO);
            }
        }
        return new PageResponse<>(mainDataRowDataListDTOS, response.getIsFirst(), response.getIsLast(), response.getTotal(), response.getPageNo(), response.getPageSize());
    }

    @Override
    public MainDataTableDTO getTable(Long id) {
        MainDataTableDTO mainDataTableDTO = null;
        //主数表名称数据
        MainDataTable mainDataTable = mainDataTableMapper.selectById(id);
        //表字段数据
        List<MainDataField> mainDataFieldList = mainDataFieldMapper.selectList(new QueryWrapper<MainDataField>().lambda().eq(MainDataField::getTableId, id).eq(MainDataField::getIsDeleted, 0));
        List<MainDataFieldDTO> fieldList = EntityUtil.copyList(mainDataFieldList, MainDataFieldDTO.class);
        mainDataTableDTO = new MainDataTableDTO();
        mainDataTableDTO.setTableName(mainDataTable.getTableName());
        mainDataTableDTO.setId(id);
        mainDataTableDTO.setFieldList(fieldList);
        return mainDataTableDTO;
    }

    @Override
    public void updateStatus(Long id, Long userId) {
        MainDataTable mainDataTable = mainDataTableMapper.selectById(id);
        if (mainDataTable == null) {
            throw new BusinessException(SystemError.SYS_411);
        }
        Integer status = mainDataTable.getStatus();
        if (1 == status) {
            mainDataTable.setStatus(0);
        } else {
            mainDataTable.setStatus(1);
        }
        mainDataTableMapper.updateById(mainDataTable);
    }

    @Override
    @Transactional
    public void deleteTable(Long id, Long userId) {
        //删除行数据
        mainDataRowDataMapper.delete(Wrappers.<MainDataRowData>lambdaQuery().eq(MainDataRowData::getTableId, id));
        //删除字段数据
        mainDataFieldDataMapper.delete(Wrappers.<MainDataFieldData>lambdaQuery().eq(MainDataFieldData::getTableId, id));
        //删除表字段
        mainDataFieldMapper.delete(Wrappers.<MainDataField>lambdaQuery().eq(MainDataField::getTableId, id));
        //删除表数据
        mainDataTableMapper.deleteById(id);
    }

    @Override
    public List<MainDataModuleDTO> queryModuleList() {

        List<MainDataTable> mainDataTableList = mainDataTableMapper.selectList(new QueryWrapper<MainDataTable>().lambda().eq(MainDataTable::getIsDeleted, 0));

        HashMap<Integer, List<MainDataModuleTableDTO>> hashMap = new HashMap<>();

        for (MainDataTable mainDataTable : mainDataTableList) {
            Integer module = mainDataTable.getModule();
            List<MainDataModuleTableDTO> list = hashMap.get(module);
            MainDataModuleTableDTO mainDataModuleTableDTO = new MainDataModuleTableDTO();
            if (null != list) {
                mainDataModuleTableDTO.setTableName(mainDataTable.getTableName());
                mainDataModuleTableDTO.setId(mainDataTable.getId());
                mainDataModuleTableDTO.setRoute(mainDataTable.getRoute());
                list.add(mainDataModuleTableDTO);
            } else {
                list = new ArrayList<>();
                mainDataModuleTableDTO.setTableName(mainDataTable.getTableName());
                mainDataModuleTableDTO.setId(mainDataTable.getId());
                mainDataModuleTableDTO.setRoute(mainDataTable.getRoute());
                list.add(mainDataModuleTableDTO);
                hashMap.put(module, list);
            }
        }

        List<MainDataModuleDTO> mainDataModuleDTOList = new ArrayList<>();
        for (Integer module : hashMap.keySet()) {
            MainDataModuleDTO mainDataModuleDTO = new MainDataModuleDTO();
            mainDataModuleDTO.setModule(module);
            mainDataModuleDTO.setList(hashMap.get(module));
            mainDataModuleDTOList.add(mainDataModuleDTO);
        }

        return mainDataModuleDTOList;
    }

    @Override
    public void updateTable(MainDataTableReq mainDataTableReq, Long userId) {
        MainDataTable mainDataTable = new MainDataTable();
        BeanUtils.copyProperties(mainDataTableReq, mainDataTable);
        mainDataTable.setModifiedId(userId);
        mainDataTable.setGmtModified(LocalDateTime.now());
        mainDataTableMapper.updateById(mainDataTable);
    }

    @Override
    public List<MainDataRowDTO> queryData(Long id) {
        List<MainDataRowData> mainDataRowDataList = mainDataRowDataMapper.selectList(new QueryWrapper<MainDataRowData>().lambda().eq(MainDataRowData::getTableId, id).eq(MainDataRowData::getIsDeleted, 0).eq(MainDataRowData::getStatus, 0));
        List<MainDataRowDTO> mainDataRowDTOList = new ArrayList<>();
        if (CollectionUtils.isEmpty(mainDataRowDataList)) {
            return mainDataRowDTOList;
        }
        List<MainDataField> mainDataFieldList = mainDataFieldMapper.selectList(new QueryWrapper<MainDataField>().lambda().eq(MainDataField::getStatus, 0).eq(MainDataField::getIsDeleted, 0).eq(MainDataField::getTableId, id));
        //行数据里表字段对应的值
        List<Long> rowIdList = mainDataRowDataList.stream().map(MainDataRowData::getId).collect(Collectors.toList());
        List<MainDataFieldData> mainDataFieldDataList = mainDataFieldDataMapper.selectList(new QueryWrapper<MainDataFieldData>().lambda().eq(MainDataFieldData::getIsDeleted, 0).eq(MainDataFieldData::getStatus, 0).in(MainDataFieldData::getRowId, rowIdList));

        HashMap<String, MainDataFieldData> hashMap = new HashMap<>(mainDataFieldList.size());

        for (MainDataFieldData mainDataFieldData : mainDataFieldDataList) {
            String key = mainDataFieldData.getRowId() + ":" + mainDataFieldData.getFieldId();
            hashMap.put(key, mainDataFieldData);
        }


        for (Long rowId : rowIdList) {
            MainDataRowDTO mainDataRowDTO = new MainDataRowDTO();
            mainDataRowDTO.setId(rowId);
            List<MainDataRowDTO.FieldData> fieldDataList = new ArrayList<>();
            for (MainDataField mainDataField : mainDataFieldList) {
                MainDataRowDTO.FieldData fieldData = new MainDataRowDTO.FieldData();
                String key = rowId + ":" + mainDataField.getId();
                fieldData.setFieldName(mainDataField.getFieldName());
                MainDataFieldData mainDataFieldData = hashMap.get(key);
                fieldData.setFieldValue(mainDataFieldData.getFieldValue());
                fieldData.setId(mainDataFieldData.getId());
                fieldDataList.add(fieldData);
            }
            mainDataRowDTO.setList(fieldDataList);
            mainDataRowDTOList.add(mainDataRowDTO);
        }
        return mainDataRowDTOList;
    }

    @Override
    public List<MainDataRowFieldDataDTO> queryDataField(Long tid, Long fid) {
        QueryWrapper<MainDataFieldData> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(MainDataFieldData::getIsDeleted, 0).eq(MainDataFieldData::getStatus, 0).eq(MainDataFieldData::getTableId, tid).eq(MainDataFieldData::getFieldId, fid);
        List<MainDataFieldData> mainDataFieldDataList = mainDataFieldDataMapper.selectList(queryWrapper);
        List<MainDataRowFieldDataDTO> mainDataRowFieldDataDTOList = EntityUtil.copyList(mainDataFieldDataList, MainDataRowFieldDataDTO.class);
        return mainDataRowFieldDataDTOList;
    }

    @Override
    public List<MainDataRowFieldDataDTO> queryDataFieldLikeName(MainDataRowFieldDataReq req) {
        QueryWrapper<MainDataFieldData> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(req.getName())) {
            queryWrapper.lambda().like(MainDataFieldData::getFieldValue, req.getName());
        }
        queryWrapper.lambda().eq(MainDataFieldData::getIsDeleted, 0).eq(MainDataFieldData::getStatus, 0).eq(MainDataFieldData::getTableId, req.getTid()).eq(MainDataFieldData::getFieldId, req.getFid());
        List<MainDataFieldData> mainDataFieldDataList = mainDataFieldDataMapper.selectList(queryWrapper);
        List<MainDataRowFieldDataDTO> mainDataRowFieldDataDTOList = EntityUtil.copyList(mainDataFieldDataList, MainDataRowFieldDataDTO.class);
        //保存顺序去重
        HashMap<String, MainDataRowFieldDataDTO> map = new HashMap<>();
        for (MainDataRowFieldDataDTO mainDataRowFieldDataDTO : mainDataRowFieldDataDTOList) {
            map.put(mainDataRowFieldDataDTO.getFieldValue(), mainDataRowFieldDataDTO);
        }
        List<MainDataRowFieldDataDTO> list = new ArrayList<>(map.values());
        return list;
    }

    @Override
    public List<MainDataRowFieldDataDTO> groupByDataField(Long tid, Long fid) {
        QueryWrapper<MainDataFieldData> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(MainDataFieldData::getIsDeleted, 0).eq(MainDataFieldData::getStatus, 0).eq(MainDataFieldData::getTableId, tid).eq(MainDataFieldData::getFieldId, fid).groupBy(MainDataFieldData::getFieldValue);
        List<MainDataFieldData> mainDataFieldDataList = mainDataFieldDataMapper.selectList(queryWrapper);
        List<MainDataRowFieldDataDTO> mainDataRowFieldDataDTOList = EntityUtil.copyList(mainDataFieldDataList, MainDataRowFieldDataDTO.class);
        return mainDataRowFieldDataDTOList;
    }

}
